﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Security.Cryptography;

namespace XLT_MobileTest
{
    public partial class Form1 : Form
    {
        const string SITE_URL = "http://xlt.mahdimedia.de";
        char[] SPECIAL_CHARS = new char[] {',','.',';',':','-','_',' ',
                                                 '\'','#','+','*','~','´','"',
                                                 '\\','?','!','§','$','%','&',
                                                 '/','(',')','{','}','[',']',
                                                 '=','<','>','|','µ','@','€',
                                                 '^','°'};
        
        private uint _stack = 0;            // stapel/fach 0-5
        private int[] _stack_words = new int[5];
        private int _current_word_index = 0;
        private Vocab _current_word;

        private string _sessionId = "";
        private Image _schrankBG;

        private List<VocabList> _vocabLists;
        private List<Vocab> _selectedWords;

        private Settings _settings;

        public Form1()
        {
            InitializeComponent();

            _schrankBG = (Image)pictureBox2.Image.Clone();
            _vocabLists = new List<VocabList>();
            _selectedWords = new List<Vocab>();
            _settings = new Settings(this);

            checkBox1.Checked = _settings.RequestCaseSensitive;
            checkBox2.Checked = _settings.RequestSpecialCharacters;
            checkBox3.Checked = _settings.RequestRandom;

            tb_login_name.Text = _settings.Username;
            tb_login_pwd.Text = _settings.Password;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            l_status.Text = "Verbinde ...";

            string strResponse = "";
            Exception ex = new Exception();
            Dictionary<string, string> data = new Dictionary<string,string>();
            data.Add("option","login");
            data.Add("nick", tb_login_name.Text);
            data.Add("pwd",tb_login_pwd.Text);

            strResponse = GetReponse("mobile.general.php", data, ref ex);

            if (strResponse == "0")
            {
                ShowError("Login fehlgeschlagen!","Deine Zugangsdaten sind falsch oder nicht mehr aktuell!");
                tb_login_pwd.Text = "";
                l_status.Text = "Warte auf Login ...";
            }
            else if (strResponse.Split(':').Length == 2)
            {
                _sessionId = strResponse.Split(':')[1];

                _settings.Username = tb_login_name.Text;
                _settings.Password = tb_login_pwd.Text;
                _settings.SaveSettings();

                l_status.Text = "Lade Profil ...";
                p_login.Visible = false;
                p_learning.Visible = false;
                p_lists.Visible = true;

                _vocabLists = new List<VocabList>();
                ex = new Exception();
                data = new Dictionary<string, string>();
                data.Add("option", "getLists");
                data.Add("sid", _sessionId);
                l_status.Text = "Lade Listen ...";
                string strResponse_lists = GetReponse("mobile.general.php", data, ref ex);
                string[] arrRows = strResponse_lists.Split('\n');                
                foreach (string row in arrRows)
                {
                    if (row.Length > 0)
                    {
                        string[] arrRowParts = row.Split('\t');
                        VocabList vl = new VocabList(this, Int32.Parse(arrRowParts[0]),
                                                            Int32.Parse(arrRowParts[2]),
                                                            Int32.Parse(arrRowParts[3]),
                                                            Int32.Parse(arrRowParts[4]),
                                                            float.Parse(arrRowParts[5].Replace('.',',')),
                                                            arrRowParts[1]);
                        _vocabLists.Add(vl);
                    }
                    l_status.Text = String.Format("Lade Listen ({0}) ...", _vocabLists.Count);
                }

                _vocabLists.Sort(delegate(VocabList l1, VocabList l2) { return l1.Percent.CompareTo(l2.Percent); });

                l_status.Text = "Lade Wörter ...";
                int cnt_words = 0;
                foreach (VocabList vl in _vocabLists)
                {
                    l_status.Text = String.Format("Lade Wörter von {0} ({1}) ...", vl.NameShort, cnt_words);

                    ex = new Exception();
                    data = new Dictionary<string, string>();
                    data.Add("option", "getWords");
                    data.Add("list", vl.Id.ToString());
                    data.Add("sid", _sessionId);

                    string strResponse_words = GetReponse("mobile.general.php", data, ref ex);
                    string[] arrRows_words = strResponse_words.Split('\n');

                    foreach (string row in arrRows_words)
                    {                        
                        string[] arrRow = row.Split('\t');
                        if (arrRow.Length >= 7)
                        {
                            try
                            {
                                vl.AddWord(new Vocab(this, Int32.Parse(arrRow[0]),
                                                            Int32.Parse(arrRow[1]),
                                                            vl.LanguageOrigin.Id,
                                                            Int32.Parse(arrRow[2]),
                                                            float.Parse(arrRow[3].Replace('.', ',')),
                                                            float.Parse(arrRow[4].Replace('.', ',')),
                                                            arrRow[5], arrRow[6]));
                                cnt_words++;
                            }
                            catch (Exception exep) { }
                        }
                    }
                    
                    l_status.Text = String.Format("Lade Wörter von {0} ({1}) ...", vl.NameShort, cnt_words);
                }

                refreshListListing();
                RefreshWordList();
                p_lists.Visible = true;
            }
            else
            {
                ShowError("Login fehlgeschlagen!", "Es besteht eventuell gerade keine Verbindung mit dem Internet...\n"+ex.Message);
                
                l_status.Text = "Warte auf Login ...";
            }
        }

        public string GetReponse(string script, Dictionary<string, string> data, ref Exception ex)
        {
            string response = "";
            try
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(SITE_URL + "/" + script);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                string strNewValue = "";
                int n = 0;
                foreach (string key in data.Keys)
                {
                    if (n!=0)
                        strNewValue += "&";
                    strNewValue += key+"="+data[key];
                    n++;
                }
                req.ContentLength = strNewValue.Length;
                StreamWriter stOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII);
                stOut.Write(strNewValue);
                stOut.Close();
                StreamReader stIn = new StreamReader(req.GetResponse().GetResponseStream());
                response = stIn.ReadToEnd();
                stIn.Close();

            }
            catch (Exception e)
            {
                ex = e;
            }
            return response;
        }

        private void refreshListListing()
        {
            int n = 0;
            p_listSelect.Controls.Clear();
            foreach (VocabList vl in _vocabLists)
            {
                PictureBox pb = new PictureBox();
                pb.Image = ((System.Drawing.Image)(vl.Language.FlagIcon));
                pb.Location = new System.Drawing.Point(3, 9 + (n * 22));
                pb.Name = "pb_list_flag_" + vl.Id.ToString();
                pb.Size = new System.Drawing.Size(16, 11);
                
                CheckBox cb = new CheckBox();
                cb.Font = new System.Drawing.Font("Tahoma", 8F, System.Drawing.FontStyle.Regular);
                cb.ForeColor = System.Drawing.Color.White;
                cb.Location = new System.Drawing.Point(25, 5+(n*22));
                cb.Name = "cb_list_"+vl.Id.ToString();
                cb.Size = new System.Drawing.Size(180, 20);
                cb.TabIndex = n;
                cb.Text = String.Format("{0} ({1}%) - {2} Wörter", vl.NameShort, Math.Round((double)vl.Percent,0), vl.Words.Count);
                cb.CheckStateChanged += new System.EventHandler(listListingCheckChanged);  

                // this.checkBox3.CheckStateChanged += new System.EventHandler(this.checkBox3_CheckStateChanged);

                p_listSelect.Controls.Add(pb);
                p_listSelect.Controls.Add(cb);
                
                n++;
            }
        }

        private void listListingCheckChanged(object sender, EventArgs e)
        {
            try
            {
                string[] arrNameParts = ((CheckBox)sender).Name.Split('_');
                int id = Int32.Parse(arrNameParts[2]);
                VocabList tmp_vl = _vocabLists.Find(delegate(VocabList vl) { return vl.Id == id; });
                if (tmp_vl.Selected)
                    tmp_vl.Selected = false;
                else
                    tmp_vl.Selected = true;
            }
            catch (Exception ex) 
            {
                ShowError("Parsing Error", ex.Message);
            }
        }


        public void RefreshWordList()
        {
            _selectedWords = new List<Vocab>();
            foreach (VocabList vl in _vocabLists.FindAll(delegate(VocabList vl) { return vl.Selected; }))
            {
                _selectedWords.AddRange(vl.Words);
            }

            RefreshRequest();
        }

        public void RefreshStackLogic()
        {
            _stack = 0;
            _stack_words = new int[5] { 0, 0, 0, 0, 0 };

            foreach (Vocab word in _selectedWords)
            {
                if (_settings.RequestDifficulty == RequestDifficulty.AskForForeign)
                {
                    if ((int)(Math.Round(word.LevelDifficult, 0)) - 1 < 5 && (int)(Math.Round(word.LevelDifficult, 0)) - 1 >= 0)
                    {
                        _stack_words[(int)(Math.Round(word.LevelDifficult, 0)) - 1]++;
                    }
                }
                else
                {
                    if ((int)(Math.Round(word.LevelEasy, 0)) - 1 < 5 && (int)(Math.Round(word.LevelEasy, 0)) - 1 >= 0)
                    {
                        _stack_words[(int)(Math.Round(word.LevelEasy, 0)) - 1]++;
                    }
                }
            }

            for (int n = 0; n < 5; n++)
            {
                if (_stack_words[4 - n] > 0)
                    _stack = (uint)(4 - n);
            }

            pictureBox2.Invalidate();
        }

        public void RefreshRequest()
        {
            if (_vocabLists.Exists(delegate(VocabList vl) { return vl.Selected; }))
            {
                _current_word_index = 0;
                RefreshStackLogic();

                if (_settings.RequestRandom)
                    MahdiHelper.ShuffleList(_selectedWords);

                Vocab tmp_word = null;
                if (_settings.RequestDifficulty == RequestDifficulty.AskForForeign)
                    tmp_word = _selectedWords.Find(delegate(Vocab word) { return ((uint)Math.Round(word.LevelDifficult, 0)) - 1 == _stack; });
                else
                    tmp_word = _selectedWords.Find(delegate(Vocab word) { return ((uint)Math.Round(word.LevelEasy, 0)) - 1 == _stack; });

                if (tmp_word == null)
                {
                    ShowError("Listenfehler", String.Format("In den ausgewählten Listen befinden sich leider keine gültigen Vokabeln mehr.\nstack:{0}", _stack));
                    p_learning.Visible = false;
                    p_lists.Visible = true;
                }
                else
                {
                    _current_word = tmp_word;
                    RefreshRequestView();
                }
            }
        }

        /// <summary>
        /// This function refreshes the current vocabulary-request just in view and not in content
        /// </summary>
        public void RefreshRequestView()
        {
            if (_settings.RequestDifficulty == RequestDifficulty.AskForForeign)
            {
                pb_learning_flagFrom.Image = _current_word.Language.FlagIcon;
                pb_learning_flagTo.Image = _current_word.LanguageOrigin.FlagIcon;
                pb_learning_difficulty0.Image = _current_word.LanguageOrigin.FlagIcon;
                pb_learning_difficulty1.Image = _current_word.Language.FlagIcon;

                l_learning_request.Text = _current_word.Translation;
            }
            else
            {
                pb_learning_flagFrom.Image = _current_word.LanguageOrigin.FlagIcon;
                pb_learning_flagTo.Image = _current_word.Language.FlagIcon;
                pb_learning_difficulty0.Image = _current_word.Language.FlagIcon;
                pb_learning_difficulty1.Image = _current_word.LanguageOrigin.FlagIcon;

                l_learning_request.Text = _current_word.Content;
            }

            tb_learning_input.Text = "";
        }

        private void pictureBox2_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(Color.FromArgb(57, 62, 72));

            e.Graphics.DrawImage(_schrankBG, 0, 0);
            e.Graphics.DrawString(_selectedWords.Count.ToString(), new Font("Tahoma", 8, FontStyle.Bold), new SolidBrush(Color.Black), 18, 1);

            e.Graphics.DrawString(_stack_words[4].ToString(), new Font("Tahoma", 10, FontStyle.Bold), new SolidBrush(Color.Black), 17, 19);
            e.Graphics.DrawString(_stack_words[3].ToString(), new Font("Tahoma", 10, FontStyle.Bold), new SolidBrush(Color.Black), 17, 50);
            e.Graphics.DrawString(_stack_words[2].ToString(), new Font("Tahoma", 10, FontStyle.Bold), new SolidBrush(Color.Black), 17, 81);
            e.Graphics.DrawString(_stack_words[1].ToString(), new Font("Tahoma", 10, FontStyle.Bold), new SolidBrush(Color.Black), 17, 112);
            e.Graphics.DrawString(_stack_words[0].ToString(), new Font("Tahoma", 10, FontStyle.Bold), new SolidBrush(Color.Black), 17, 137);

            int offsetY = 22; // 53,84,115,140
            switch (_stack)
            {
                case 3:
                    offsetY = 53;
                    break;
                case 2:
                    offsetY = 84;
                    break;
                case 1:
                    offsetY = 115;
                    break;
                case 0:
                    offsetY = 140;
                    break;
            }
            e.Graphics.FillPolygon(new SolidBrush(Color.White), new Point[] { new Point(58, 3+offsetY), new Point(64,offsetY), new Point(64,offsetY+6) });
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {

        }

        private void p_learning_GotFocus(object sender, EventArgs e)
        {

        }

        private void pictureBox3_Click(object sender, EventArgs e)
        {

        }

        private void button5_Click(object sender, EventArgs e)
        {
            p_learning.Visible = false;
            p_lists.Visible = true;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (_selectedWords.Count > 0)
            {
                p_learning.Visible = true;
                p_lists.Visible = false;
            }
            else
            {
                ShowError("Keine Liste", "Es wurden keine Lernlisten ausgewählt, oder die ausgewählten beinhalteten keine Wörter!");
            }
        }

        private void pictureBox8_Click(object sender, EventArgs e)
        {
            p_about.Visible = false;
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            p_about.Visible = true;
        }

        public static string GetApplicationPath()
        {
            return System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
        }

        private void pictureBox9_Click(object sender, EventArgs e)
        {
            HideError();
        }

        public void ShowError(string header, string text)
        {
            p_error.Visible = true;
            l_errorHeader.Text = header;
            l_errorText.Text = text;

            if (text.Length > 30 * 8)
            {
                l_errorText.Size = new Size(l_errorText.Size.Width, l_errorText.Size.Height + ((int)Math.Floor((text.Length - (30 * 8)) / 30)));
            }
            else
            {
                l_errorText.Size = new Size(l_errorText.Size.Width, 150);
            }
        }

        public void HideError()
        {
            p_error.Visible = false;
            l_errorHeader.Text = "";
            l_errorText.Text = "";
        }

        private void pictureBox6_Click(object sender, EventArgs e)
        {
            if (checkBox3.Checked)
                checkBox3.CheckState = CheckState.Unchecked;
            else
                checkBox3.CheckState = CheckState.Checked;
        }

        private void pictureBox5_Click(object sender, EventArgs e)
        {
            if (checkBox2.Checked)
                checkBox2.CheckState = CheckState.Unchecked;
            else
                checkBox2.CheckState = CheckState.Checked;
        }

        private void pictureBox4_Click(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
                checkBox1.CheckState = CheckState.Unchecked;
            else
                checkBox1.CheckState = CheckState.Checked;
        }

        private void checkBox1_CheckStateChanged(object sender, EventArgs e)
        {
            _settings.RequestCaseSensitive = checkBox1.Checked;
            _settings.SaveSettings();
        }

        private void checkBox2_CheckStateChanged(object sender, EventArgs e)
        {
            _settings.RequestSpecialCharacters = checkBox2.Checked;
            _settings.SaveSettings();
        }

        private void checkBox3_CheckStateChanged(object sender, EventArgs e)
        {
            _settings.RequestRandom = checkBox3.Checked;
            _settings.SaveSettings();
        }

        private void pb_learning_difficulty_Click(object sender, EventArgs e)
        {
            if (_settings.RequestDifficulty == RequestDifficulty.AskForForeign)
                _settings.RequestDifficulty = RequestDifficulty.AskForNative;
            else
                _settings.RequestDifficulty = RequestDifficulty.AskForForeign;
        }

        private void pb_learning_difficulty1_Click(object sender, EventArgs e)
        {
            if (_settings.RequestDifficulty == RequestDifficulty.AskForForeign)
                _settings.RequestDifficulty = RequestDifficulty.AskForNative;
            else
                _settings.RequestDifficulty = RequestDifficulty.AskForForeign;
        }

        public void CheckLearningInput(bool force)
        {
            if (_current_word != null && _selectedWords.Count > 0)
            {
                string i = tb_learning_input.Text.Trim();
                string c = _current_word.ContentFiltered.Trim();
                if (_settings.RequestDifficulty == RequestDifficulty.AskForNative)
                {
                    c = _current_word.TranslationFiltered.Trim();
                }

                if (!_settings.RequestSpecialCharacters)
                {   // filter special chars
                    foreach (char schar in SPECIAL_CHARS)
                    {
                        i = i.Replace(schar.ToString(), "");
                        c = c.Replace(schar.ToString(), "");
                    }
                }

                Font old_font = (Font)tb_learning_input.Font.Clone();
                

                if ((!_settings.RequestCaseSensitive && i.ToLower() == c.ToLower())
                    || (_settings.RequestCaseSensitive && i == c))
                {
                    tb_learning_input.Font = new Font("Tahoma", 9f, FontStyle.Bold);
                    tb_learning_input.ForeColor = Color.Green;

                    if (_settings.RequestDifficulty == RequestDifficulty.AskForForeign)
                        _current_word.LevelDifficult++;
                    else
                        _current_word.LevelEasy++;

                    _current_word.Submit();
                    
                    tb_learning_input.Font = old_font;
                    tb_learning_input.ForeColor = Color.Black;

                    l_status.Text = i + "!=" + c;

                    RefreshRequest();
                }
                else if (force)
                {
                    tb_learning_input.Font = new Font("Tahoma", 9f, FontStyle.Bold);
                    tb_learning_input.ForeColor = Color.Red;

                    if (_settings.RequestDifficulty == RequestDifficulty.AskForForeign)
                        _current_word.LevelDifficult = 1;
                    else
                        _current_word.LevelEasy = 1;

                    tb_learning_input.Font = old_font;
                    tb_learning_input.ForeColor = Color.Black;

                    l_status.Text = i + "!=" + c + "!";

                    RefreshRequest();
                }
            }
        }
        


        public Settings Settings { get { return _settings; } set { _settings = value; } }

        private void menuItem2_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void tb_learning_input_KeyUp(object sender, KeyEventArgs e)
        {
            CheckLearningInput(false);
        }

        private void tb_learning_input_TextChanged(object sender, EventArgs e)
        {
            CheckLearningInput(false);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            CheckLearningInput(true);
        }   
    }
}